home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
vol11n08.zip
/
DEMO7.C
< prev
next >
Wrap
Text File
|
1992-02-08
|
27KB
|
631 lines
// DEMO7.C --- Pen-centric Windows application that accepts
// handwritten input, then displays the contents of
// the RCRESULT structure, the enumerated symbol
// strings, or the symbol graph.
// Copyright (C) 1992 Ray Duncan
#define WIN31
#define dim(x) (sizeof(x) / sizeof(x[0])) // returns no. of elements
#define BUFMAX 80 // size of scratch buffers
#include "windows.h"
#include "penwin.h"
#include "demo7.h"
HANDLE hInst; // instance handle
HWND hWndFrame = 0; // frame window handle
HWND hWndText = 0; // child text window handle
HWND hWndWrite = 0; // child writing window handle
HANDLE hPenWin = 0; // Pen Windows module handle
int CharX = 0; // average char width
int CharY = 0; // char height
int CurLine = 0; // current line number
int MaxLine = 0; // lines per window
int EnumCount = 0; // translation counter
int DisplayMode = IDM_RCRESULT; // current display format
char szFrameClass[] = "DemoFrameClass"; // name of frame window class
char szTextClass[] = "DemoTextClass"; // child text window class
char szWriteClass[] = "DemoWriteClass"; // child writing window class
struct decodeInt { // simple structure to
int Code; // associate integer values
char * Name; }; // with character strings
struct decodeSYV { // simple structure to
SYV Code; // associate SYV values
char * Name; }; // with character strings
struct decodeInt recogResults[] = { // values returned by
REC_OK, "REC_OK", // Recognize() function
REC_ABORT, "REC_ABORT",
REC_ALC, "REC_ALC",
REC_BADEVENTREF, "REC_BADEVENTREF",
REC_BADHPENDATA, "REC_BADHPENDATA",
REC_BUFFERTOOSMALL, "REC_BUFFERTOOSMALL",
REC_BUSY, "REC_BUSY",
REC_CLVERIFY, "REC_CLVERIFY",
REC_DICT, "REC_DICT",
REC_DONE, "REC_DONE",
REC_ERRORLEVEL, "REC_ERRORLEVEL",
REC_GUIDE, "REC_GUIDE",
REC_HREC, "REC_HREC",
REC_HWND, "REC_HWND",
REC_INVALIDREF, "REC_INVALIDREF",
REC_LANGUAGE, "REC_LANGUAGE",
REC_NOCOLLECTION, "REC_NOCOLLECTION",
REC_NOINPUT, "REC_NOINPUT",
REC_NOTABLET, "REC_NOTABLET",
REC_OEM, "REC_OEM",
REC_OOM, "REC_OOM",
REC_OVERFLOW, "REC_OVERFLOW",
REC_PARAMERROR, "REC_PARAMERROR",
REC_PCM, "REC_PCM",
REC_POINTEREVENT, "REC_POINTEREVENT",
REC_RECTEXCLUDE, "REC_RECTEXCLUDE",
REC_RECTBOUND, "REC_RECTBOUND",
REC_RESULTMODE, "REC_RESULTMODE",
REC_TERMBOUND, "REC_TERMBOUND",
REC_TERMEX, "REC_TERMEX",
REC_TERMOEM, "REC_TERMOEM",
REC_TERMPENUP, "REC_TERMPENUP",
REC_TERMRANGE, "REC_TERMRANGE",
REC_TERMTIMEOUT, "REC_TERMTIMEOUT", } ;
struct decodeInt rctypeResults[] = { // RCRESULT data types
RCRT_UNIDENTIFIED, "RCRT_UNIDENTIFIED",
RCRT_GESTURE, "RCRT_GESTURE",
RCRT_NOSYMBOLMATCH, "RCRT_NOSYMBOLMATCH",
RCRT_PRIVATE, "RCRT_PRIVATE",
RCRT_NORECOG, "RCRT_NORECOG",
RCRT_ALREADYPROCESSED, "RCRT_ALREADYPROCESSED",
RCRT_GESTURETRANSLATED, "RCRT_GESTURETRANSLATED",
RCRT_GESTURETOKEYS, "RCRT_GESTURETOKEYS", } ;
struct decodeSYV syvSystemValue[] = { // system values for SYVs
SYV_BEGINOR, "SYV_BEGINOR",
SYV_EMPTY, "SYV_EMPTY",
SYV_ENDOR, "SYV_ENDOR",
SYV_NULL, "SYV_NULL",
SYV_OR, "SYV_OR",
SYV_SOFTNEWLINE, "SYV_SOFTNEWLINE",
SYV_UNKNOWN, "SYV_UNKNOWN", } ;
struct decodeSYV syvGestureValue[] = { // gesture values for SYVs
SYV_BACKSPACE, "SYV_BACKSPACE",
SYV_CLEAR, "SYV_CLEAR",
SYV_CLEARWORD, "SYV_CLEARWORD",
SYV_COPY, "SYV_COPY",
SYV_CORRECT, "SYV_CORRECT",
SYV_CUT, "SYV_CUT",
SYV_EXTENDSELECT, "SYV_EXTENDSELECT",
SYV_PASTE, "SYV_PASTE",
SYV_RETURN, "SYV_RETURN",
SYV_SPACE, "SYV_SPACE",
SYV_TAB, "SYV_TAB",
SYV_UNDO, "SYV_UNDO",
SYV_USER, "SYV_USER", } ;
//
// WinMain --- entry point from Windows. Registers window classes,
// creates windows, registers pen app, and processes messages until
// WM_QUIT received.
//
int PASCAL WinMain(HANDLE hInstance,
HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
hInst = hInstance; // save this instance handle
if(!hPrevInstance) // if first instance,
if(!InitApplication(hInstance)) // register window class
return(FALSE); // exit if couldn't register
if(!InitInstance(hInstance, nCmdShow)) // create this instance's window
{
MessageBox(0, "Initialization failed!", "DEMO7", MB_OK|MB_ICONSTOP);
return(FALSE);
}
RegisterPenApp(RPA_DEFAULT, TRUE); // enable HEDIT/BEDIT controls
while(GetMessage(&msg, NULL, 0, 0)) // while message != WM_QUIT
{
TranslateMessage(&msg); // translate virtual key codes
DispatchMessage(&msg); // dispatch message to window
}
return(msg.wParam); // return code = WM_QUIT value
}
//
// InitApplication --- registers window classes for this application
//
BOOL InitApplication(HANDLE hInstance)
{
WNDCLASS wc;
BOOL bParent;
BOOL bText;
BOOL bWrite;
// set parameters for frame window class
wc.style = CS_HREDRAW | CS_VREDRAW; // class style
wc.lpfnWndProc = FrameWndProc; // class callback function
wc.cbClsExtra = 0; // extra per-class data
wc.cbWndExtra = 0; // extra per-window data
wc.hInstance = hInstance; // handle of class owner
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // default icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // default cursor
wc.hbrBackground = GetStockObject(WHITE_BRUSH); // background color
wc.lpszMenuName = "DemoMenu"; // name of menu resource
wc.lpszClassName = szFrameClass; // name of window class
bParent = RegisterClass(&wc); // register frame window class
// set parameters for text output child window class
wc.lpfnWndProc = TextWndProc; // class callback function
wc.hIcon = NULL; // default icon
wc.lpszMenuName = NULL; // name of menu resource
wc.lpszClassName = szTextClass; // name of window class
bText = RegisterClass(&wc); // register text child class
// set parameters for writing input child window class
wc.lpfnWndProc = WriteWndProc; // class callback function
wc.lpszClassName = szWriteClass; // name of window class
bWrite = RegisterClass(&wc); // register writing child class
return(bParent && bText && bWrite); // return success/failure flag
}
//
// InitInstance --- creates frame window for this application instance
//
BOOL InitInstance(HANDLE hInstance, int nCmdShow)
{
hWndFrame = CreateWindow( // create frame window
szFrameClass, // window class name
"Pen Windows Demo #7", // text for title bar
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, CW_USEDEFAULT, // default position
CW_USEDEFAULT, CW_USEDEFAULT, // default size
NULL, // no parent window
NULL, // use class default menu
hInstance, // window owner
NULL // unused pointer
);
if(!hWndFrame) return(FALSE); // error, can't create window
ShowWindow(hWndFrame, nCmdShow); // make frame window visible
UpdateWindow(hWndFrame); // force WM_PAINT message
return(TRUE); // return success flag
}
//
// FrameWndProc --- callback function for application frame window
//
long FAR PASCAL FrameWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
{
switch (wMsg)
{
case WM_CREATE: // creating frame window
hWndText = CreateWindow( // create child text window
szTextClass, // window class name
NULL, // text for title bar
WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER, // style
0, 0, 0, 0, // position and size
hWnd, // frame window is parent
0, // child window identifier
hInst, // window owner
NULL); // unused pointer
hWndWrite = CreateWindow( // create child writing window
szWriteClass, // window class name
NULL, // text for title bar
WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER, // style
0, 0, 0, 0, // position and size
hWnd, // frame window is parent
0, // child window identifier
hInst, // window owner
NULL); // unused pointer
break;
case WM_SIZE: // resize & position children:
MoveWindow(hWndWrite, // writing input window
0, 0, LOWORD(lParam)/2, HIWORD(lParam), TRUE);
MoveWindow(hWndText, // text output window
LOWORD(lParam)/2, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
return(0);
case WM_COMMAND: // menu command received,
DoCommand(hWnd, wParam); // decode it
break;
case WM_DESTROY: // window being destroyed
PostQuitMessage(0); // force WM_QUIT message
break;
default: // let Windows handle it
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
return(0);
}
//
// TextWndProc --- callback function for child text window
//
long FAR PASCAL TextWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
{
TEXTMETRIC tm;
HDC hdc;
switch(wMsg)
{
case WM_CREATE: // creating text child window
hdc = GetDC(hWnd); // get device context
GetTextMetrics(hdc, &tm); // get text metrics
CharX = tm.tmAveCharWidth; // save character size
CharY = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hWnd, hdc); // release device context
return(0);
case WM_SIZE: // resize/position in progress
CurLine = 0; // reset current line number
MaxLine = HIWORD(lParam)/CharY; // no. of lines in window
return(0);
default:
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
}
//
// WriteWndProc --- callback function for child writing window
//
long FAR PASCAL WriteWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
{
RC rc; // recognition context
HDC hdc; // device context handle
PAINTSTRUCT ps; // painting info structure
RECT rect; // receives client rectangle
REC result; // status from Recognize()
LPRCRESULT rcresult; // recognition results
char buff1[BUFMAX]; // scratch buffer
int i; // scratch variable
switch(wMsg)
{
case WM_PAINT: // window needs repainting
hdc = BeginPaint(hWnd, &ps); // get device context
GetClientRect(hWnd, &rect); // get client rectangle
DrawText(hdc, // put legend in writing area
"Writing Area", -1, &rect,
DT_CENTER | DT_TOP | DT_SINGLELINE);
EndPaint(hWnd, &ps); // release device context
break;
case WM_LBUTTONDOWN: // "pen-down" in writing area
if(IsPenEvent(wMsg, GetMessageExtraInfo()))
{
InvalidateRect(hWnd, NULL, TRUE); // erase both windows
UpdateWindow(hWnd);
InvalidateRect(hWndText, NULL, TRUE);
UpdateWindow(hWndText);
CurLine = 0; // reset current line number
InitRC(hWndWrite, &rc); // set default RC values
rc.hwnd = hWnd; // this window gets the results
rc.rglpdf[0] = NULL; // assume no dictionary
DisplayLine("Calling Recognize function.");
result = Recognize(&rc); // request pen input
strcpy(buff1, "Recognize result: unknown.");
for(i = 0; i < dim(recogResults); i++)
{ // decode Recognize() value
if(recogResults[i].Code == result)
wsprintf(buff1, "Recognize result: %s.",
(LPSTR) recogResults[i].Name);
}
DisplayLine(buff1); // display Recognize() status
};
return(0);
case WM_RCRESULT: // receiving recognition results
rcresult = (LPRCRESULT) lParam; // get pointer to results
DisplayLine("Message WM_RCRESULT received.");
switch(DisplayMode) // display results according
{ // to current display mode
case IDM_RCRESULT:
ShowRCResult(rcresult); // RCRESULT data structure
break;
case IDM_SYMGRAPH: // symbol graph
ShowSymbolGraph(rcresult);
break;
case IDM_SYMSTRINGS: // candidate symbol strings
ShowSymbolStrings(rcresult);
break;
}
return(0);
default:
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
}
//
// ShowRCResult -- displays contents of RCRESULT data structure
//
void ShowRCResult(LPRCRESULT rcresult)
{
char buff1[BUFMAX]; // scratch buffer
char buff2[BUFMAX]; // scratch buffer
int i; // scratch variable
wsprintf(buff1, "rcresult.syg.cHotSpot = %0d", rcresult->syg.cHotSpot);
DisplayLine(buff1); // number of valid hot spots
wsprintf(buff1, "rcresult.syg.nFirstBox = %0d", rcresult->syg.nFirstBox);
DisplayLine(buff1); // box index, first result char
wsprintf(buff1, "rcresult.syg.lpsye = %04X:%04Xh",
HIWORD(rcresult->syg.lpsye), LOWORD(rcresult->syg.lpsye));
DisplayLine(buff1); // pointer to SYE nodes
wsprintf(buff1, "rcresult.syg.cSye = %0d", rcresult->syg.cSye);
DisplayLine(buff1); // no. of SYEs in symbol graph
wsprintf(buff1, "rcresult.syg.lpsyc = %04X:%04Xh",
HIWORD(rcresult->syg.lpsyc), LOWORD(rcresult->syg.lpsyc));
DisplayLine(buff1); // pointer to SYC nodes
wsprintf(buff1, "rcresult.syg.cSyc = %0d", rcresult->syg.cSyc);
DisplayLine(buff1); // number of SYCs
if(rcresult->wResultsType == RCRT_DEFAULT) // decode result type
DisplayLine("rcresult.wResultsType = RCRT_DEFAULT");
else // if not RCRT_DEFAULT,
{ // check each possible flag
for(i = 0; i < dim(rctypeResults); i++)
{
if(rctypeResults[i].Code & rcresult->wResultsType)
{
wsprintf(buff1, "rcresult.wResultsType = %s",
(LPSTR) rctypeResults[i].Name);
DisplayLine(buff1);
}
}
}
wsprintf(buff1, "rcresult.cSyv = %d", rcresult->cSyv);
DisplayLine(buff1); // number of symbols
wsprintf(buff1, "rcresult.lpsyv = %04X:%04Xh",
HIWORD(rcresult->lpsyv), LOWORD(rcresult->lpsyv));
DisplayLine(buff1); // pointer to symbol string
SymbolToCharacter(rcresult->lpsyv, BUFMAX, buff2, NULL);
wsprintf(buff1, "rcresult.lpsyv -> %s", (LPSTR) buff2);
DisplayLine(buff1); // best bet translated string
wsprintf(buff1, "rcresult.hSyv = %04Xh", rcresult->hSyv);
DisplayLine(buff1); // handle for SYV memory block
wsprintf(buff1, "rcresult.nBaseLine = %0d", rcresult->nBaseLine);
DisplayLine(buff1); // baseline of written input
wsprintf(buff1, "rcresult.nMidLine = %0d", rcresult->nMidLine);
DisplayLine(buff1); // midline of written input
wsprintf(buff1, "rcresult.hpendata = %04Xh", rcresult->hpendata);
DisplayLine(buff1); // pen data memory block handle
wsprintf(buff1, "rcresult.rectBoundInk = (%d, %d) - (%d, %d)",
rcresult->rectBoundInk.left, rcresult->rectBoundInk.top,
rcresult->rectBoundInk.right, rcresult->rectBoundInk.bottom);
DisplayLine(buff1); // bounding rectangle for ink
wsprintf(buff1, "rcresult.pntEnd = (%d, %d)",
rcresult->pntEnd.x, rcresult->pntEnd.y);
DisplayLine(buff1); // recognition termination point
wsprintf(buff1, "rcresult.lprc = %04X:%04Xh",
HIWORD(rcresult->lprc), LOWORD(rcresult->lprc));
DisplayLine(buff1); // address of RC structure
}
//
// ShowSymbolStrings -- enumerates and displays candidate symbol strings
//
void ShowSymbolStrings(LPRCRESULT rcresult)
{
FARPROC lpProc; // far pointer for callback
char buff1[BUFMAX]; // scratch buffer
wsprintf(buff1, "Symbol graph has %d possible translations.",
GetSymbolCount(&(rcresult->syg)));
DisplayLine(buff1); // display no. of candidates
EnumCount = 0; // then display each candidate
lpProc = MakeProcInstance(EnumFunc, hInst);
EnumSymbols(&(rcresult->syg), 1000, lpProc, NULL);
FreeProcInstance(lpProc);
}
//
// ShowSymbolGraph -- displays contents of symbol graph
//
void ShowSymbolGraph(LPRCRESULT rcresult)
{
LPSYE lpSye = rcresult->syg.lpsye; // first symbol element
int cSye = rcresult->syg.cSye; // no. of symbol elements
int Level = 0; // SYV_BEGINOR nesting level
SYV syv; // current symbol value
char syvChar; // current character
int syvCl; // current confidence level
int syvType; // current symbol type
char buff1[BUFMAX], buff2[BUFMAX]; // scratch buffers
int i, j; // scratch variable
char * p; // scratch pointer
SymbolToCharacter(rcresult->lpsyv, BUFMAX, buff2, NULL);
wsprintf(buff1, "Preferred translation: %s", (LPSTR) buff2);
DisplayLine(buff1); // best bet translated string
DisplayLine("Start of symbol graph:"); // now dump the symbol graph
for(i = 0; i < cSye; i++)
{
syv = lpSye[i].syv; // get current symbol value
syvType = HIWORD(syv); // extract symbol type
syvChar = ChSyvToAnsi(syv); // extract character if any
syvCl = lpSye[i].cl; // get confidence level
switch(syvType) // format according to type
{
case(SYVHI_SPECIAL): // SYV system values
if(syv == SYV_BEGINOR) // start of char. choice list
{
if(Level) // if stuff already waiting
DisplayLine(buff1); // in buffer, display it
p = buff1 + wsprintf(buff1, "{ ");
Level++; // count nesting levels
}
else if(syv == SYV_OR) // choice list separator
{
p += wsprintf(p, " | ");
}
else if(syv == SYV_ENDOR) // end of char. choice list
{
wsprintf(p, " }");
DisplayLine(buff1); // display choice list
p = buff1;
Level--; // count nesting levels
}
else // decode & display all
{ // other system SYV values
for(j = 0; j < dim(syvSystemValue); j++)
{
if(syvSystemValue[j].Code == syv)
DisplayLine(syvSystemValue[j].Name);
}
}
break;
case(SYVHI_ANSI): // SYV ASCII characters
if(syv == SYV_SPACENULL) // format char. & conf. level
wsprintf(buff2, "NO SPACE [%d%%]", syvCl);
else if(syvChar == ' ')
wsprintf(buff2, "SPACE [%d%%]", syvCl);
else if(syvChar < ' ')
wsprintf(buff2, "%02Xh [%d%%]", syvChar, syvCl);
else
wsprintf(buff2, "%c [%d%%]", syvChar, syvCl);
if(Level) // within char. choice list?
p += wsprintf(p, "%s", (LPSTR) buff2); // yes, append
else // no, display text now
DisplayLine(buff2);
break;
case(SYVHI_GESTURE): // SYV gestures
for(j = 0; j < dim(syvGestureValue); j++)
{ // decode gesture value
if(syvGestureValue[j].Code == syv)
{ // found match, display it
DisplayLine(syvGestureValue[j].Name);
break;
}
if(j == dim(syvGestureValue))
{ // no match, show hex value
wsprintf(buff1, "gesture: %08lXh", syv);
DisplayLine(buff1);
}
}
break;
case(SYVHI_KANJI): // Kanji
case(SYVHI_SHAPE): // shapes
case(SYVHI_UNICODE): // Unicode
case(SYVHI_VKEY): // virtual keys
default: // whatever else
wsprintf(buff1, "type %d: %08lXh", syvType, syv);
DisplayLine(buff1);
}
}
DisplayLine("End of symbol graph.");
}
//
// DisplayLine --- displays a string in the text output child window
//
void DisplayLine(char * szOut)
{
RECT rect;
HDC hdc;
hdc = GetDC(hWndText); // get device context
GetClientRect(hWndText, &rect); // get client rectangle
if(CurLine == MaxLine) // at bottom of window?
{
ScrollWindow(hWndText, 0, -CharY, // yes, scroll window up
NULL, NULL);
UpdateWindow(hWndText);
CurLine--;
}
TextOut(hdc, 0, CurLine * CharY, // display text in window
szOut, strlen(szOut));
CurLine++; // move to next line
ReleaseDC(hWndText, hdc); // release device context
return;
}
//
// DoCommand --- handles menu command messages for the frame window
//
void DoCommand(HWND hWnd, WORD wParam)
{
FARPROC lpProc; // far pointer to callback
HMENU hMenu;
switch(wParam) // decode it
{
case IDM_EXIT: // user picked File-Quit
SendMessage (hWnd, WM_CLOSE, 0, 0L);
break;
case IDM_RCRESULT: // user picked a display
case IDM_SYMGRAPH: // format, save it and
case IDM_SYMSTRINGS: // check/uncheck menu items
hMenu = GetMenu(hWnd);
CheckMenuItem(hMenu, DisplayMode, MF_UNCHECKED);
DisplayMode = wParam;
CheckMenuItem(hMenu, DisplayMode, MF_CHECKED);
break;
default: // unknown command, ignore it
break;
}
}
//
// EnumFunc --- the callback function for EnumSymbols(). During
// evaluation of a symbol graph, this function is entered
// repetitively with a pointer to each candidate symbol array.
// The symbol array is translated to a character string and displayed.
//
int FAR PASCAL EnumFunc(LPSYV lpSyv, int cSyv, VOID FAR * lpData)
{
char buff1[BUFMAX]; // scratch buffer
char buff2[BUFMAX]; // scratch buffer
SymbolToCharacter(lpSyv, BUFMAX, // convert symbol string to
buff2, NULL); // char string and display it
wsprintf(buff1, "Translation #%d is: %s.", ++EnumCount, (LPSTR) buff2);
DisplayLine(buff1);
return(TRUE); // TRUE to continue enumeration
}